package com.teng.smartdrawer.view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.support.v4.view.MotionEventCompat;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.teng.smartdrawer.R;
import com.teng.smartdrawer.utils.MetricsUtil;
import com.teng.smartdrawer.view.swipelistview.SwipeMenu;
import com.teng.smartdrawer.view.swipelistview.SwipeMenuAdapter;
import com.teng.smartdrawer.view.swipelistview.SwipeMenuCreator;
import com.teng.smartdrawer.view.swipelistview.SwipeMenuLayout;
import com.teng.smartdrawer.view.swipelistview.SwipeMenuView;


/**
 *
 *
 */

public class SwipeMenuLoadMoreListView extends ListView implements OnScrollListener {

    private static final String TAG = "SwipeMenuLoadMoreListView";

    /**
     * Listener that will receive notifications every time the list scrolls.
     */
    private OnScrollListener mOnScrollListener;
    private LayoutInflater mInflater;

    // footer view
    private RelativeLayout mFooterView;
    private LinearLayout mLabLoadMore;
    // private ProgressBar mProgressBarLoadMore;
    private View moreinfo;
    private ImageView progresBarWait;
    private Animation rotation;

    // Listener to process load more items when user reaches the end of the list
    private OnLoadMoreListener mOnLoadMoreListener;
    // To know if the list is loading more items
    private boolean mIsLoadingMore = false;

    private boolean mCanLoadMore = true;
    private boolean needShowEmptyHint = true;
    private int mCurrentScrollState;
    private boolean needShowLoadMore = false;
    private TextView no_more_textView;

    private static final int TOUCH_STATE_NONE = 0;
    private static final int TOUCH_STATE_X = 1;
    private static final int TOUCH_STATE_Y = 2;

    private int MAX_Y = 5;
    private int MAX_X = 3;
    private float mDownX;
    private float mDownY;
    private int mTouchState;
    private int mTouchPosition;
    private SwipeMenuLayout mTouchView;

    private SwipeMenuCreator mMenuCreator;
    private OnMenuItemClickListener mOnMenuItemClickListener;
    private OnSwipeListener mOnSwipeListener;
    private Interpolator mCloseInterpolator;
    private Interpolator mOpenInterpolator;

    public SwipeMenuLoadMoreListView(Context context) {
        super(context);
        init(context);
    }

    public SwipeMenuLoadMoreListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public SwipeMenuLoadMoreListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    private void init(Context context) {
        MetricsUtil.getCurrentWindowMetrics(context);
        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        // footer
        mFooterView = (RelativeLayout) mInflater.inflate(R.layout.activity_homepage_moreinfo, this, false);
        mLabLoadMore = (LinearLayout) mFooterView.findViewById(R.id.more_info_null);
        // mProgressBarLoadMore = (ProgressBar)
        // mFooterView.findViewById(R.id.load_more_progressBar);
        moreinfo = mFooterView.findViewById(R.id.more_info_linear);
        no_more_textView = (TextView) mFooterView.findViewById(R.id.no_more_textView);

        addFooterView(mFooterView);
        ViewGroup.LayoutParams localLayoutParams1 = this.mLabLoadMore.getLayoutParams();
        localLayoutParams1.height = (int) (MetricsUtil.getCurrentHeightSize((int) getResources().getDimension(R.dimen.activity_splash_textview_logoname_margin_bottom)) * MetricsUtil.CURRENT_DENSITY
                / 160.0D);
        mLabLoadMore.setLayoutParams(localLayoutParams1);

        ViewGroup.LayoutParams localLayoutParams2 = this.moreinfo.getLayoutParams();
        localLayoutParams2.height = (int) (MetricsUtil.getCurrentHeightSize((int) getResources().getDimension(R.dimen.activity_splash_textview_logoname_margin_bottom)) * MetricsUtil.CURRENT_DENSITY
                / 160.0D);
        moreinfo.setLayoutParams(localLayoutParams2);
        progresBarWait = (ImageView) mFooterView.findViewById(R.id.more_info_progress);
        rotation = AnimationUtils.loadAnimation(context, R.anim.progress_anim);
        rotation.setRepeatCount(-1);
        super.setOnScrollListener(this);

        MAX_X = dp2px(MAX_X);
        MAX_Y = dp2px(MAX_Y);
        mTouchState = TOUCH_STATE_NONE;
    }

    private int dp2px(int dp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
                getContext().getResources().getDisplayMetrics());
    }

    public static interface OnMenuItemClickListener {
        boolean onMenuItemClick(int position, SwipeMenu menu, int index);
    }

    @Override
    public void setAdapter(ListAdapter adapter) {
        super.setAdapter(new SwipeMenuAdapter(getContext(), adapter, 1) {
            @Override
            public void createMenu(SwipeMenu menu) {
                if (mMenuCreator != null) {
                    mMenuCreator.create(menu);
                }
            }

            @Override
            public void onItemClick(SwipeMenuView view, SwipeMenu menu, int index) {
                boolean flag = false;
                if (mOnMenuItemClickListener != null) {
                    flag = mOnMenuItemClickListener.onMenuItemClick(
                            view.getPosition(), menu, index);
                }
                if (mTouchView != null && !flag) {
                    mTouchView.smoothCloseMenu();
                }
            }
        });
    }

    public void setCloseInterpolator(Interpolator interpolator) {
        mCloseInterpolator = interpolator;
    }

    public void setOpenInterpolator(Interpolator interpolator) {
        mOpenInterpolator = interpolator;
    }

    public Interpolator getOpenInterpolator() {
        return mOpenInterpolator;
    }

    public Interpolator getCloseInterpolator() {
        return mCloseInterpolator;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return super.onInterceptTouchEvent(ev);
    }

    public static interface OnSwipeListener {
        void onSwipeStart(int position);

        void onSwipeEnd(int position);
    }

    public void setMenuCreator(SwipeMenuCreator menuCreator) {
        this.mMenuCreator = menuCreator;
    }

    public void setOnMenuItemClickListener(
            OnMenuItemClickListener onMenuItemClickListener) {
        this.mOnMenuItemClickListener = onMenuItemClickListener;
    }

    public void setOnSwipeListener(OnSwipeListener onSwipeListener) {
        this.mOnSwipeListener = onSwipeListener;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (ev.getAction() != MotionEvent.ACTION_DOWN && mTouchView == null)
            return super.onTouchEvent(ev);
        int action = MotionEventCompat.getActionMasked(ev);
        action = ev.getAction();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                int oldPos = mTouchPosition;
                mDownX = ev.getX();
                mDownY = ev.getY();
                mTouchState = TOUCH_STATE_NONE;

                mTouchPosition = pointToPosition((int) ev.getX(), (int) ev.getY());

                if (mTouchPosition == oldPos && mTouchView != null
                        && mTouchView.isOpen()) {
                    mTouchState = TOUCH_STATE_X;
                    mTouchView.onSwipe(ev);
                    return true;
                }

                View view = getChildAt(mTouchPosition - getFirstVisiblePosition());

                if (mTouchView != null && mTouchView.isOpen()) {
                    mTouchView.smoothCloseMenu();
                    mTouchView = null;
                    // return super.onTouchEvent(ev);
                    // try to cancel the touch event
                    MotionEvent cancelEvent = MotionEvent.obtain(ev);
                    cancelEvent.setAction(MotionEvent.ACTION_CANCEL);
                    onTouchEvent(cancelEvent);
                    return true;
                }
                if (view instanceof SwipeMenuLayout) {
                    mTouchView = (SwipeMenuLayout) view;
                }
                if (mTouchView != null) {
                    mTouchView.onSwipe(ev);
                }
                break;
            case MotionEvent.ACTION_MOVE:
                float dy = Math.abs((ev.getY() - mDownY));
                float dx = Math.abs((ev.getX() - mDownX));
                if (mTouchState == TOUCH_STATE_X) {
                    if (mTouchView != null) {
                        mTouchView.onSwipe(ev);
                    }
                    getSelector().setState(new int[]{0});
                    ev.setAction(MotionEvent.ACTION_CANCEL);
                    super.onTouchEvent(ev);
                    return true;
                } else if (mTouchState == TOUCH_STATE_NONE) {
                    if (Math.abs(dy) > MAX_Y) {
                        mTouchState = TOUCH_STATE_Y;
                    } else if (dx > MAX_X) {
                        mTouchState = TOUCH_STATE_X;
                        if (mOnSwipeListener != null) {
                            mOnSwipeListener.onSwipeStart(mTouchPosition);
                        }
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                if (mTouchState == TOUCH_STATE_X) {
                    if (mTouchView != null) {
                        mTouchView.onSwipe(ev);
                        if (!mTouchView.isOpen()) {
                            mTouchPosition = -1;
                            mTouchView = null;
                        }
                    }
                    if (mOnSwipeListener != null) {
                        mOnSwipeListener.onSwipeEnd(mTouchPosition);
                    }
                    ev.setAction(MotionEvent.ACTION_CANCEL);
                    super.onTouchEvent(ev);
                    return true;
                }
                break;
        }
        return super.onTouchEvent(ev);
    }

    /**
     * Set the listener that will receive notifications every time the list
     * scrolls.
     *
     * @param l The scroll listener.
     */
    @Override
    public void setOnScrollListener(OnScrollListener l) {
        mOnScrollListener = l;
    }

    /**
     * Register a callback to be invoked when this list reaches the end (last
     * item be visible)
     *
     * @param onLoadMoreListener The callback to run.
     */

    public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) {
        mOnLoadMoreListener = onLoadMoreListener;
    }

    @SuppressLint("ShowToast")
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

        if (mOnScrollListener != null) {
            mOnScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
        }

        if (mOnLoadMoreListener != null) {

            if (visibleItemCount == totalItemCount) {
                moreinfo.setVisibility(View.INVISIBLE);
                if (needShowEmptyHint) {
                    mLabLoadMore.setVisibility(View.VISIBLE);
                } else {
                    mLabLoadMore.setVisibility(View.INVISIBLE);
                }

                if (needShowLoadMore) {
                    moreinfo.setVisibility(View.VISIBLE);
                    mLabLoadMore.setVisibility(View.INVISIBLE);
                    mIsLoadingMore = true;
                    onLoadMore();
                }

                return;
            }

            boolean loadMore = firstVisibleItem + visibleItemCount >= totalItemCount;
            //LogUtils.e("loadmoredata" , (firstVisibleItem+visibleItemCount)+" ===== "+totalItemCount);16940047
            if (!mIsLoadingMore && loadMore && mCurrentScrollState != SCROLL_STATE_IDLE) {
                if (!mCanLoadMore) {
                    if (needShowEmptyHint)
                        mLabLoadMore.setVisibility(View.VISIBLE);
                    return;
                }
                moreinfo.setVisibility(View.VISIBLE);
                progresBarWait.startAnimation(this.rotation);
                mLabLoadMore.setVisibility(View.GONE);
                mIsLoadingMore = true;
                onLoadMore();
            }

        }

    }

    public boolean isNeedShowLoadMore() {
        return needShowLoadMore;
    }

    public void setNeedShowLoadMore(boolean needShowLoadMore) {
        this.needShowLoadMore = needShowLoadMore;
    }

    public void onScrollStateChanged(AbsListView view, int scrollState) {
        mCurrentScrollState = scrollState;

        if (mOnScrollListener != null) {
            mOnScrollListener.onScrollStateChanged(view, scrollState);
        }

    }

    public void setMoreInfoText(String infoText) {
        if (infoText != null && !"".equals(infoText)) {
            no_more_textView.setText(infoText);
        }
    }

    public void setCanLoadMore(boolean canLoadMore) {
        mCanLoadMore = canLoadMore;
        if (!mCanLoadMore) {
            if (needShowEmptyHint)
                mLabLoadMore.setVisibility(View.VISIBLE);
        } else {
            mLabLoadMore.setVisibility(View.INVISIBLE); // 底部加载更多
        }
    }

    public void setNeedShowEmptyHint(boolean isNeed) {
        needShowEmptyHint = isNeed;
    }

    public void onLoadMore() {
//        Log.d(TAG, "onLoadMore");
        if (mOnLoadMoreListener != null) {
            mOnLoadMoreListener.onLoadMore();
        }
    }

    /**
     * Notify the loading more operation has finished
     */
    public void onLoadMoreComplete() {
        mIsLoadingMore = false;
        moreinfo.setVisibility(View.GONE);
        progresBarWait.clearAnimation();
    }

    /**
     * Interface definition for a callback to be invoked when list reaches the
     * last item (the user load more items in the list)
     */
    public interface OnLoadMoreListener {
        /**
         * Called when the list reaches the last item (the last item is visible
         * to the user)
         */
        public void onLoadMore();
    }

}